package com.nova.bluetooth.helpUtils;

import com.dido.fastblelib.utils.HexUtil;
import com.nova.bluetooth.bean.AdvertisingField;
import com.nova.bluetooth.myEnum.DenoiseMode;
import com.nova.bluetooth.myEnum.DenoiseModeLevel;
import com.nova.bluetooth.myEnum.EQModel;
import com.nova.bluetooth.myEnum.FindDeviceModel;
import com.nova.bluetooth.myEnum.ImmersionModel;
import com.nova.bluetooth.myEnum.KeyFunctionClickModel;
import com.nova.bluetooth.myEnum.KeyFunctionControlModel;
import com.nova.bluetooth.myEnum.LightModel;
import com.nova.bluetooth.myEnum.SleepModel;
import com.nova.bluetooth.myEnum.SpaceModel;
import com.nova.bluetooth.myEnum.TFModel;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

public class BluetoothDataUtil {

    public static final String BLE_CMD_DISCONNECT = "A000040100"; //蓝牙断开（BLE）
    public static final String BLE_CMD_RESET = "A000010100"; //恢复出厂设置

    public static final String BLE_CMD_GET_LEFT_BATTERY = "A000050100"; //左耳电量获取
    public static final String BLE_CMD_GET_RIGHT_BATTERY = "A000050100"; //右耳电量获取
    public static final String BLE_CMD_GET_BIN_BATTERY = "A000050102"; //仓电量获取
    public static final String BLE_CMD_GET_BOX_BATTERY = "A000050101"; //音箱电量获取
    public static final String BLE_CMD_GET_HEADSET_BATTERY = "A000050101"; //骨气传导、头戴式电量获取


    public static final String BLE_CMD_GET_EQ = "A0000701FF"; //获取EQ状态
    public static final String BLE_CMD_GET_DENOISE = "A0000B01FF";//降噪状态获取

    public static final String BLE_CMD_GET_KEY_FUNCTION1 = "A00006030001FF";
    public static final String BLE_CMD_GET_KEY_FUNCTION2 = "A00006030101FF";
    public static final String BLE_CMD_GET_KEY_FUNCTION3 = "A00006030002FF";
    public static final String BLE_CMD_GET_KEY_FUNCTION4 = "A00006030102FF";

    public static final String BLE_CMD_GET_SLEEP_MODEL = "aa640100";//睡眠模式获取
    public static final String BLE_CMD_GET_SLEEP_TIME_CANCEL = "aa6502FFFF";//取消睡眠定时

    public static final String BLE_CMD_GET_SPACE_SOUND = "aa800100";//获取空间音效
    public static final String BLE_CMD_GET_IMMERSION_SOUND = "A0000C01FF";//获取沉浸式音频模式

    public static final String BLE_CMD_GET_VOLUME = "aa0001FF"; //获取音量
    public static final String BLE_CMD_ADD_VOLUME = "aa02011e"; //增加音量
    public static final String BLE_CMD_SUB_VOLUME = "aa01011e";  //减少音量

    public static final String BLE_CMD_GET_PLAY_STATE = "aa070100";  //获取播放状态
    public static final String BLE_CMD_LAST = "aa090100";  //上一曲
    public static final String BLE_CMD_PLAY_PAUSE = "aa080100";  //播放暂停
    public static final String BLE_CMD_NEXT = "aa0a0100";  //获取播放状态
    public static final String BLE_CMD_PLAY = "aa080101";
    public static final String BLE_CMD_PAUSE = "aa080102";

    public static final String BLE_CMD_GET_TF_MODEL = "aa480100";  //获取TF模式状态
    public static final String BLE_CMD_SET_TF_MODEL = "aa450100";  //设置TF模式
    public static final String BLE_CMD_GET_BLUETOOTH_MODEL = "aa460100";  //设置蓝牙模式

    public static final String BLE_CMD_GET_LIGHT = "aa6b0100";  //获取灯光状态

    public static final String BLE_CMD_GET_FM = "aa690100";//获取FM状态
    public static final String BLE_CMD_GET_RADIO = "aa740100";//搜索电台
    public static final String BLE_CMD_LAST_FM = "aa720100";  //上一电台
    public static final String BLE_CMD_NEXT_FM = "aa730100";  //下一电台
    public static final String BLE_CMD_MUTE_SET = "aa750100";  //静音设置

    public static final String BLE_CMD_EAR_DETECTION = "A0000D01FF";  //入耳检测开关状态获取
    public static final String BLE_CMD_GAME_MODEL = "A0000901FF";  //获取游戏模式状态
    public static final String BLE_CMD_GET_FOCUS_MODEL = "aa860100";//获取专注模式
    public static final String BLE_CMD_GET_AI_TRANSLATE = "aa510102"; //获取当前对耳翻译状态
    public static final String BLE_CMD_GET_AI_AUDIO_TRANSCRIPTION = "aa510102"; //获取录音转写状态




    public static List<AdvertisingField> parseAdvertisingData(byte[] advertisingData) {
        List<AdvertisingField> fields = new ArrayList<>();
        int index = 0;

        while (index < advertisingData.length) {
            int length = advertisingData[index++] & 0xFF;
            if (length == 0) {
                break;
            }
            if (index + length > advertisingData.length) {
                break;
            }
            int type = advertisingData[index++] & 0xFF;
            byte[] data = new byte[length - 1];
            System.arraycopy(advertisingData, index, data, 0, length - 1);
            fields.add(new AdvertisingField(type, data));
            index += length - 1;
        }

        return fields;
    }

    /**
     * 合并两个数组
     *
     * @param array1
     * @param array2
     * @return
     */
    public static byte[] concatenateByteArrays(byte[] array1, byte[] array2) {
        ByteBuffer buffer = ByteBuffer.allocate(array1.length + array2.length);
        buffer.put(array1);
        buffer.put(array2);
        return buffer.array();
    }

    /**
     * 校验和
     *
     * @param b
     * @return 返回两位的十六进制字符串
     */
    public static String CheckSum(byte[] b) {
        int i, sum = 0;
        for (i = 0; i < b.length; i++) sum += b[i];//将每个数相加
        if (sum > 0xff) {
            sum = ~sum;
            sum += 1;
        }
        sum = sum & 0xff;
        String str = Integer.toHexString(sum);
        if (str.length() == 1) {
            str = "0" + str;
        }
        return str;
    }

    /**
     * 校验和
     *
     * @param b 要校验的byte数组
     * @return
     */
    public static byte calculateCheckSum(byte[] b) {
        int i, sum = 0;
        for (i = 0; i < b.length; i++) {
            sum += b[i]; // 将每个数相加
        }

        if (sum > 0xff) {
            sum = ~sum;
            sum += 1;
        }
        sum = sum & 0xff;
        return (byte) sum;
    }

    /**
     * 计算检验和并把校验和放在末尾，返回整条发给设备的指令
     *
     * @param b
     * @return
     */
    public static byte[] calculateCheckSumResult(byte[] b) {
        int i, sum = 0;
        for (i = 0; i < b.length; i++) {
            sum += b[i]; // 将每个数相加
        }

        if (sum > 0xff) {
            sum = ~sum;
            sum += 1;
        }

        sum = sum & 0xff;

        byte[] result = new byte[b.length + 1];
        System.arraycopy(b, 0, result, 0, b.length);
        result[b.length] = (byte) sum;

        return result;
    }


    public static String getDeviceTypeFromData(byte[] data_ff) {
        if (data_ff == null || data_ff.length < 7) {
            LogUtil.e("Invalid data_ff array");
            return "Invalid data";
        }


        byte[] deviceTypeBytes = new byte[3];
        System.arraycopy(data_ff, 4, deviceTypeBytes, 0, 3);

        // 将字节数组转换为字符串
        return HexUtil.encodeHexStr(deviceTypeBytes);
    }

    /**
     * 软件版本号
     *
     * @param data_ff
     * @return
     */
    public static String getVersionFromData(byte[] data_ff) {
        if (data_ff == null || data_ff.length < 4) {
            LogUtil.e("Invalid data_ff array");
            return "Invalid data";
        }

        // 提取版本号字节
        byte highByte = data_ff[2];
        byte lowByte = data_ff[3];

        // 将两个字节合并为一个int值
        int version = ((highByte & 0xFF) << 8) | (lowByte & 0xFF);
        return String.valueOf(version);
    }


    /**
     * 固件版本号
     *
     * @param data_ff
     * @return
     */
    public static String getFirmwareVersionFromData(byte[] data_ff) {
        if (data_ff == null || data_ff.length < 6) {
            LogUtil.e("Invalid data_ff array");
            return "Invalid data";
        }

        // 提取版本号字节
        byte highByte = data_ff[4];
        byte lowByte = data_ff[5];

        // 将两个字节合并为一个int值
        int version = ((highByte & 0xFF) << 8) | (lowByte & 0xFF);
        return String.valueOf(version);
    }

    /**
     * 硬件版本号
     *
     * @param data_ff
     * @return
     */
    public static String getHardwareVersionFromData(byte[] data_ff) {
        if (data_ff == null || data_ff.length < 8) {
            LogUtil.e("Invalid data_ff array");
            return "Invalid data";
        }

        // 提取版本号字节
        byte highByte = data_ff[6];
        byte lowByte = data_ff[7];

        // 将两个字节合并为一个int值
        int version = ((highByte & 0xFF) << 8) | (lowByte & 0xFF);
        return String.valueOf(version);
    }


    public static String getSerialNumberFromData(byte[] data) {
        if (data == null || data.length < 28) {
            LogUtil.e("Invalid data array");
            return "Invalid data";
        }

        // 提取 SN 字节
        byte[] snBytes = new byte[5];
        System.arraycopy(data, 23, snBytes, 0, 5);

        // 将字节数组转换为字符串
        return HexUtil.encodeHexStr(snBytes);
    }

    public static String getBLEMacFromData(byte[] data) {
        if (data == null || data.length < 13) {
            LogUtil.e("Invalid data array");
            return "Invalid data";
        }

        // 提取 mac
        byte[] snBytes = new byte[6];
        System.arraycopy(data, 7, snBytes, 0, 6);

        // 将字节数组转换为字符串
        return HexUtil.encodeHexStr(snBytes);
    }

    public static String getBTMacFromData(byte[] data) {
        if (data == null || data.length < 19) {
            LogUtil.e("Invalid data array");
            return "Invalid data";
        }

        // 提取 mac
        byte[] snBytes = new byte[6];
        System.arraycopy(data, 13, snBytes, 0, 6);

        // 将字节数组转换为字符串
        return HexUtil.encodeHexStr(snBytes);
    }

    public static byte[] getEQSetCMD(EQModel eqModel, int deviceType) {
        byte[] mBytes = new byte[5];
        mBytes[0] = (byte) 0xA0;
        mBytes[1] = (byte) 0x00;
        mBytes[2] = (byte) 0x07;
        mBytes[3] = (byte) 0x01;
        switch (eqModel) {
            case SSQVP:
                mBytes[4] = (byte) 0x00;
                break;
            case POP:
                mBytes[4] = (byte) 0x01;
                break;
            case ROCK:
                mBytes[4] = (byte) 0x02;
                break;
            case CLASSIC:
                mBytes[4] = (byte) 0x03;
                break;
            case LYRIC:
                mBytes[4] = (byte) 0x04;
                break;
            case SOFT:
                mBytes[4] = (byte) 0x05;
                break;
        }
        return calculateCheckSumResult(mBytes);
    }

    /**
     * 入耳检测
     *
     * @param isOpen
     * @return
     */
    public static byte[] getEarDetectionCMD(boolean isOpen) {
        byte[] mBytes = new byte[5];
        mBytes[0] = (byte) 0xAA;
        mBytes[1] = (byte) 0x00;
        mBytes[2] = (byte) 0x0D;
        mBytes[3] = (byte) 0x01;
        if (isOpen) {
            mBytes[4] = (byte) 0x00; //开
        } else {
            mBytes[4] = (byte) 0x01; //关
        }
        return calculateCheckSumResult(mBytes);
    }


    /**
     * 0: 游戏模式（关）
     * 1: 游戏模式（开）
     *
     * @param isOpen
     * @return
     */
    public static byte[] getGameModelSetCMD(boolean isOpen) {
        byte[] mBytes = new byte[5];
        mBytes[0] = (byte) 0xA0;
        mBytes[1] = (byte) 0x00;
        mBytes[2] = (byte) 0x09;
        mBytes[3] = (byte) 0x01;
        if (isOpen) {
            mBytes[4] = (byte) 0x00; //开
        } else {
            mBytes[4] = (byte) 0x01; //关
        }
        return calculateCheckSumResult(mBytes);
    }


    public static byte[] getKeyFunctionSetCMD(KeyFunctionClickModel clickModel, KeyFunctionControlModel controlModel) {
        byte[] mBytes = new byte[7];
        mBytes[0] = (byte) 0xA0;
        mBytes[1] = (byte) 0x00;
        mBytes[2] = (byte) 0x06;
        mBytes[3] = (byte) 0x03;
        switch (clickModel) {
            case LeftDoubleClick:
                mBytes[4] = (byte) 0x00;
                mBytes[5] = (byte) 0x01;
                break;
            case RightDoubleClick:
                mBytes[4] = (byte) 0x01;
                mBytes[5] = (byte) 0x01;
                break;
            case LeftThreeShot:
                mBytes[4] = (byte) 0x00;
                mBytes[5] = (byte) 0x02;
                break;
            case RightThreeShot:
                mBytes[4] = (byte) 0x01;
                mBytes[5] = (byte) 0x02;
                break;
        }

        switch (controlModel) {
            case PlayOrPause:
                mBytes[6] = (byte) 0x00;
                break;
            case Previous:
                mBytes[6] = (byte) 0x01;
                break;
            case Next:
                mBytes[6] = (byte) 0x02;
                break;
            case VolumeUp:
                mBytes[6] = (byte) 0x03;
                break;
            case VolumeDown:
                mBytes[6] = (byte) 0x04;
        }
        return calculateCheckSumResult(mBytes);
    }


    public static byte[] getDenoiseSetCMD(DenoiseMode denoiseMode, DenoiseModeLevel level) {
        byte[] mBytes = new byte[5];
        mBytes[0] = (byte) 0xA0;
        mBytes[1] = (byte) 0x00;
        mBytes[2] = (byte) 0x0B;
        mBytes[3] = (byte) 0x01;
        switch (denoiseMode) {
            case NOISE_MODE_OFF:
                mBytes[4] = (byte) 0x00;
                break;
            case NOISE_MODE_DENOISE:
                mBytes[4] = (byte) 0x01;
                break;
            case NOISE_MODE_TRANSPARENT:
                mBytes[4] = (byte) 0x02;
                break;
        }

//        switch (level) {
//            case NOISE_MODE_LEVEL_NULL:
//                mBytes[4] = (byte) 0x03;
//                break;
//            case NOISE_MODE_LEVEL_MILD:
//                mBytes[4] = (byte) 0x00;
//                break;
//            case NOISE_MODE_LEVEL_MEDIUM:
//                mBytes[4] = (byte) 0x01;
//                break;
//            case NOISE_MODE_LEVEL_SEVERE:
//                mBytes[4] = (byte) 0x02;
//                break;
//        }
        return calculateCheckSumResult(mBytes);
    }


    public static byte[] getFindDeviceSetCMD(FindDeviceModel findDeviceModel) {
        byte[] mBytes = new byte[5];
        mBytes[0] = (byte) 0xA0;
        mBytes[1] = (byte) 0x00;
        mBytes[2] = (byte) 0x0A;
        mBytes[3] = (byte) 0x01;
        switch (findDeviceModel) {
            case LEFT_AND_RIGHT_EAR:
                mBytes[4] = (byte) 0x00;
                break;
            case LEFT_EAR:
                mBytes[4] = (byte) 0x01;
                break;
            case RIGHT_EAR:
                mBytes[4] = (byte) 0x02;
                break;
            case CANCEL:
                mBytes[4] = (byte) 0x03;
                break;
        }
        return calculateCheckSumResult(mBytes);
    }


    public static byte[] getSleepTimeCMD(int hour, int minute) {
        byte[] mBytes = new byte[5];
        mBytes[0] = (byte) 0xAA;
        mBytes[1] = (byte) 0x65;
        mBytes[2] = (byte) 0x02;
        mBytes[3] = (byte) hour;
        mBytes[4] = (byte) minute;
        return calculateCheckSumResult(mBytes);
    }


    public static byte[] getSleepSetCMD(SleepModel sleepModel) {
        byte[] mBytes = new byte[4];
        mBytes[0] = (byte) 0xAA;
        mBytes[1] = (byte) 0x63;
        mBytes[2] = (byte) 0x01;
        switch (sleepModel) {
            case Standard:
                mBytes[3] = (byte) 0x00;
                break;
            case Sleep:
                mBytes[3] = (byte) 0x01;
                break;
            case LowPower:
                mBytes[3] = (byte) 0x02;
                break;
        }
        return calculateCheckSumResult(mBytes);
    }


    public static byte[] getSpaceModelSetCMD(SpaceModel model) {
        byte[] mBytes = new byte[4];
        mBytes[0] = (byte) 0xAA;
        mBytes[1] = (byte) 0x80;
        mBytes[2] = (byte) 0x01;
        switch (model) {
            case Music:
                mBytes[3] = (byte) 0x01;
                break;
            case Sport:
                mBytes[3] = (byte) 0x02;
                break;
            case Video:
                mBytes[3] = (byte) 0x03;
                break;
            case Empty:
                mBytes[3] = (byte) 0x04;
                break;
        }
        return calculateCheckSumResult(mBytes);
    }

    public static byte[] getImmersionModelSetCMD(ImmersionModel model) {
        byte[] mBytes = new byte[5];
        mBytes[0] = (byte) 0xA0;
        mBytes[1] = (byte) 0x00;
        mBytes[2] = (byte) 0x0C;
        mBytes[3] = (byte) 0x01;
        switch (model) {
            case Off:
                mBytes[4] = (byte) 0x00;
                break;
            case Statical:
                mBytes[4] = (byte) 0x01;
                break;
            case Dynamic:
                mBytes[4] = (byte) 0x02;
                break;
        }
        return calculateCheckSumResult(mBytes);
    }

    public static byte[] getFocusModelSetCMD(boolean isOpen) {
        byte[] mBytes = new byte[4];
        mBytes[0] = (byte) 0xAA;
        mBytes[1] = (byte) 0x86;
        mBytes[2] = (byte) 0x01;
        if (isOpen) {
            mBytes[3] = (byte) 0x01; //开
        } else {
            mBytes[3] = (byte) 0x02; //关
        }
        return calculateCheckSumResult(mBytes);
    }


    public static byte[] getAiTranslateSetCMD(boolean isOpen) {
        byte[] mBytes = new byte[4];
        mBytes[0] = (byte) 0xAA;
        mBytes[1] = (byte) 0x51;
        mBytes[2] = (byte) 0x01;
        if (isOpen) {
            mBytes[3] = (byte) 0x01; //开
        } else {
            mBytes[3] = (byte) 0x00; //关
        }
        return calculateCheckSumResult(mBytes);
    }

    public static byte[] getAiAudioTranscriptionSetCMD(boolean isOpen) {
        byte[] mBytes = new byte[4];
        mBytes[0] = (byte) 0xAA;
        mBytes[1] = (byte) 0x52;
        mBytes[2] = (byte) 0x01;
        if (isOpen) {
            mBytes[3] = (byte) 0x01; //开
        } else {
            mBytes[3] = (byte) 0x00; //关
        }
        return calculateCheckSumResult(mBytes);
    }

    public static byte[] getVolumeSetCMD(int volume) {
        byte[] mBytes = new byte[4];
        mBytes[0] = (byte) 0xAA;
        mBytes[1] = (byte) 0x00;
        mBytes[2] = (byte) 0x01;
        mBytes[3] = (byte) volume;
        return calculateCheckSumResult(mBytes);
    }

    public static byte[] getTFSetCMD(TFModel model) {
        byte[] mBytes = new byte[4];
        mBytes[0] = (byte) 0xAA;
        switch (model) {
            case TF:
                mBytes[1] = (byte) 0x45;
                break;
            case Bluetooth:
                mBytes[1] = (byte) 0x46;
                break;
        }
        mBytes[2] = (byte) 0x01;
        mBytes[3] = (byte) 0x00;
        return calculateCheckSumResult(mBytes);
    }

    public static byte[] getLightSetCMD(LightModel model) {
        byte[] mBytes = new byte[4];
        mBytes[0] = (byte) 0xAA;
        mBytes[1] = (byte) 0x6a;
        mBytes[2] = (byte) 0x01;
        switch (model) {
            case DefModel:
                mBytes[3] = (byte) 0x00;
                break;
            case Light1:
                mBytes[3] = (byte) 0x01;
                break;
            case Light2:
                mBytes[3] = (byte) 0x02;
                break;
            case Light3:
                mBytes[3] = (byte) 0x03;
                break;
            case Light4:
                mBytes[3] = (byte) 0x04;
                break;
            case Light5:
                mBytes[3] = (byte) 0x05;
                break;
        }
        return calculateCheckSumResult(mBytes);
    }


    public static byte[] getFMModelSetCMD(boolean isOpen) {
        byte[] mBytes = new byte[4];
        mBytes[0] = (byte) 0xAA;
        if (isOpen){
            mBytes[1] = (byte) 0x70;
        }else {
            mBytes[1] = (byte) 0x71;
        }
        mBytes[2] = (byte) 0x01;
        mBytes[3] = (byte) 0x00;
        return calculateCheckSumResult(mBytes);
    }
}
